#!/usr/bin/env python
'''PyLibrarian label generator (for generating book labels to be printed on
   Avery 5160/8160 or compatible address labels)'''

try:
  import json
except ImportError:
  import simplejson as json
  
import ConfigParser
from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import cm, mm, inch, pica
from reportlab.graphics.barcode.code128 import Code128

config = ConfigParser.ConfigParser()
config.readfp(open('config.ini'))

libraryName = config.get('library', 'name')

def cmpData(a, b):
  '''Comparison function for sorting lists of dicts by the data key of the dict'''
  if a['data'] < b['data']: return -1
  elif a['data'] > b['data']: return 1
  else: return 0

def generateLabels(data):
  '''Generates book labels using the data dictionary passed in. Each code should be
  an integer, and will be printed using 9 digits (padded with zeroes if necessary).
  Up to 30 labels will be generated per page for compatibility with Avery
  5160/8160 or most other address label forms containing 30 per sheet. The text
  of a PDF document is returned (to be sent back to the browser).'''
  pdf = Canvas("foo.pdf", pagesize = letter)  # PDF name is irrelevant as it only ever exists in RAM
  pdf.setFillColorRGB(0, 0, 0)
  
  imgX = startX = 45
  imgY = startY = letter[1] - 71
  
  for res in data:
    txt = '%09d' % res['code']
    
    if imgX > 600:
      # Start a new page
      imgX = startX
      imgY = startY
      pdf.showPage()
    
    # Generate and draw the barcode
    codeImg = Code128(txt, barWidth=.9)
    codeImg.drawOn(pdf, imgX, imgY)
    pdf.setFont("Courier", 12)
    pdf.drawCentredString(imgX + 64.5, imgY - 10, txt)
    pdf.setFont("Courier", 10)
    pdf.drawCentredString(imgX + 64.5, imgY - 20, res['data'].upper()[:20].strip())
    
    imgY -= 73    # Move down to the next label location
    
    if imgY < 50:
      # Start a new column
      imgY = startY
      imgX += 200
  
  pdf.showPage()
  return pdf.getpdfdata()
  
def generateLibrarianCardholderSheet(data):
  '''Generates a sheet with 30 cardholder barcodes per page. This is useful
     for smaller libraries that want to keep a master sheet in case one of their
     cardholders forgets his/her card.'''
  pdf = Canvas("bar.pdf", pagesize = letter)  # PDF name is irrelevant as it only ever exists in RAM
  pdf.setFillColorRGB(0, 0, 0)
  
  imgX = startX = 45
  imgY = startY = letter[1] - 71
  
  data.sort(cmpData)    # Keep the librarian sheets in alphabetical order
  
  for res in data:
    txt = '%08d' % res['code']
    
    if imgX > 600:
      # Start a new page
      imgX = startX
      imgY = startY
      pdf.showPage()
    
    # Generate and draw the barcode
    codeImg = Code128(txt, barWidth=.9)
    codeImg.drawOn(pdf, imgX, imgY)
    pdf.setFont("Courier", 12)
    pdf.drawCentredString(imgX + 55, imgY - 10, txt)
    pdf.setFont("Courier", 10)
    pdf.drawCentredString(imgX + 55, imgY - 20, res['data'].upper()[:50].strip())
    
    imgY -= 73    # Move down to the next label location
    
    if imgY < 50:
      # Start a new column
      imgY = startY
      imgX += 200
  
  pdf.showPage()
  return pdf.getpdfdata()
  
def generateCards(data):
  '''Generates library cards using the data dictionary passed in. Each user id
  should be an integer, and will be printed using 8 digits (padded with zeroes
  if necessary). The resulting PDF can be printed on Avery 5390 or a compatible
  template.'''
  pdf = Canvas("bar.pdf", pagesize = letter)  # PDF name is irrelevant as it only ever exists in RAM
  pdf.setFillColorRGB(0, 0, 0)
  
  imgX = startX = 120
  imgY = startY = letter[1] - 135
  
  for res in data:
    txt = '%08d' % res['code']
    
    if imgX > 600:
      # Start a new page
      imgX = startX
      imgY = startY
      pdf.showPage()
    
    # Generate and draw the barcode
    codeImg = Code128(txt, barWidth=.9)
    codeImg.drawOn(pdf, imgX, imgY)
    pdf.setFont("Courier", 12)
    pdf.drawCentredString(imgX + 55, imgY - 10, txt)
    pdf.setFont("Courier", 10)
    pdf.drawCentredString(imgX + 55, imgY - 20, res['data'].upper()[:25].strip())
    pdf.setFont("Courier", 10)
    pdf.drawCentredString(imgX + 55, imgY - 40, libraryName.upper()[:30].strip())
    
    imgY -= 170    # Move down to the next label location
    
    if imgY < 50:
      # Start a new column
      imgY = startY
      imgX += 260
  
  pdf.showPage()
  return pdf.getpdfdata()